package query_understanding.query_language.doc_entity_tree;

import edu.stanford.nlp.ling.IndexedWord;
import javafx.util.Pair;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


import query_understanding.query_language.doc_entity_tree.QueryEdge.BaseEdge;
import semantic_compute.entity_linking.schema.EntityLinkingResult;


/**
 * Created by julianzliu on 4/22/2017.
 */
public class QueryNode {

    public enum NodeType{
        BASE, DOCUMENT, ENTITY, CONCEPT, KEYWORD, VARIABLE
    }


    public static class BaseNode extends QueryElement.AbstractQueryElement {

        public NodeType nodeType;

        // TODO
        // 克隆重点关注对象
        public Set<BaseEdge> edgesSet;

        /***************************
         * 查询执行过程中使用
         */
        public BaseEdge inE;
        public Set<BaseEdge>  outE;

        public Boolean solved;
        public Boolean solveable;


        public BaseNode(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            this.nodeType = NodeType.BASE;
            this.edgesSet = new HashSet<>();
            this.solveable = false;
            this.solved = false;
            this.outE = new HashSet<>();
            this.inE = null;
        }

        /*
        public BaseNode(BaseNode othor){
            this.nodeType = othor.nodeType;
            this.edgesSet = new HashSet<>(othor.edgesSet);
        }
        */

        public BaseNode copy(){
            return new BaseNode();
        }

        public BaseNode(NodeType nodeType){
            this.nodeType = nodeType;
        }

        //至依存句法分析树的链接
        //  --->
        List< Pair<BaseEdge, BaseNode> >  childs;
        //  <---
        Pair<BaseEdge, BaseNode> parent;


    }


    /*
    public static class DocumentNode extends BaseNode {

        public DocumentNode(){
            this.nodeType = NodeType.DOCUMENT;
        }

    }
    */

    public static class EntityNode extends BaseNode{

        public String yago_id;

        public String yago_label;

        public Double score;

        public EntityLinkingResult.LinkedEntity entity;

        public IndexedWord mainToken;

        public List<IndexedWord> allTokens;

        public EntityNode(){
            super();
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            this.nodeType = NodeType.ENTITY;
            this.allTokens = new ArrayList<>();
        }

        public EntityNode(EntityNode other){
            //super(other);
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            this.nodeType = NodeType.ENTITY;
            this.yago_label = other.yago_label;
            this.yago_id = other.yago_id;
            this.score = other.score;
            this.entity = other.entity;
            this.mainToken = other.mainToken;
            this.allTokens = other.allTokens;
            this.edgesSet = new HashSet<>();
        }

        public EntityNode copy(){
            EntityNode new_node = new EntityNode( this );
            return new_node;
        }


    }

    public static class ConceptNode extends BaseNode{

        public String yago_id;

        public String yago_label;

        public Double score;

        public IndexedWord mainToken;

        public List<IndexedWord> allTokens;

        public ConceptNode(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            this.nodeType = NodeType.CONCEPT;
            this.allTokens = new ArrayList<>();
        }

        public ConceptNode copy(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            ConceptNode new_node = new ConceptNode();
            new_node.yago_id = this.yago_id;
            new_node.yago_label = this.yago_label;
            new_node.score = this.score;
            new_node.mainToken = this.mainToken;
            new_node.allTokens = this.allTokens;
            new_node.edgesSet = new HashSet<>();
            return new_node;
        }


    }

    public static class VariableNode extends BaseNode{

        public VariableNode(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            this.nodeType = NodeType.VARIABLE;
            this.edgesSet = new HashSet<>();
        }

        public VariableNode copy(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            VariableNode new_node = new VariableNode();
            new_node.edgesSet = new HashSet<>();
            return new_node;
        }

    }

    public static class KeywordNode extends BaseNode{

        public String text;

        public IndexedWord mainToken;

        public List<IndexedWord> allTokens;

        public KeywordNode(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            this.text = "";
            this.nodeType = NodeType.KEYWORD;
            this.allTokens = new ArrayList<>();
        }

        public KeywordNode copy(){
            this.elementType = QueryElement.ElementType.NODE_TYPE;
            KeywordNode new_node = new KeywordNode();
            new_node.text = this.text;
            new_node.allTokens = this.allTokens;
            new_node.edgesSet = new HashSet<>();
            return  new_node;
        }
    }



}
